package com.xiaochen.autohttpinvoker;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
import org.springframework.util.ClassUtils;

import java.util.Set;
/**
*  RpcProvider的扫描
* @author chenkangyong
* @date 2019/3/19 15:38
*/
@Slf4j
public class RpcProviderScanner implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
    private Environment environment;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        String remotePrefix= environment.resolvePlaceholders("${rpc.provider.baseUrl}");
        String basePackage= environment.resolvePlaceholders("${rpc.provider.basePackage}");
        ClassPathScanningCandidateComponentProvider beanScanner = new ClassPathScanningCandidateComponentProvider(false);
        beanScanner.addIncludeFilter(new AnnotationTypeFilter(RpcProvider.class));

        long startTime = System.currentTimeMillis();
        Set<BeanDefinition> beanDefinitions = beanScanner.findCandidateComponents(basePackage);
        log.info("扫描含有RpcProvider注解的Bean共用[{}]个",beanDefinitions.size());
        for (BeanDefinition beanDefinition : beanDefinitions) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HttpInvokerServiceExporter.class);
            try {
                if(null==beanDefinition.getBeanClassName()){
                    continue;
                }
                Class<?> impClazz= ClassUtils.forName(beanDefinition.getBeanClassName(), this.getClass().getClassLoader());
                String simpleClassName = impClazz.getSimpleName();
                String camel = simpleClassName.substring(0, 1).toLowerCase() + simpleClassName.substring(1);
                builder.addPropertyReference("service", camel);
                Class<?>[] interClazz = impClazz.getInterfaces();
                if(null==interClazz||interClazz.length!=1){
                    throw new BeanInvalidException(beanDefinition.getBeanClassName()+"没有实现接口或者超过1个");
                }
                builder.addPropertyValue("serviceInterface", interClazz[0]);
                BeanDefinition register = builder.getRawBeanDefinition();
                String intSimpleName = interClazz[0].getSimpleName();
                String url = remotePrefix + intSimpleName.substring(0, 1).toLowerCase() + intSimpleName.substring(1);
                beanDefinitionRegistry.registerBeanDefinition(url, register);
                log.info("----注册提供者[{}]，路径为[{}]----", camel, url);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        log.info("扫描共花费了[{}ms]", System.currentTimeMillis()-startTime);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment=environment;
    }
}
